package com.justgame.project.cloud.common.util;

import com.justgame.project.cloud.common.constant.Const;
import com.justgame.project.cloud.common.exception.Exc;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.tomcat.util.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Token工具类
 *
 * @Author ZhouWeiBo
 * @Time 2021年4月22日11点07分
 */

public class TokenUtil {
    private final Logger logger = LoggerFactory.getLogger(TokenUtil.class);

    public static SecretKey generalKey(String salt) {
        if (StringUtils.isBlank(salt)) {
            salt = Const.DEFAULT_SALT_TOKEN;
        }
        // 本地的密码解码
        byte[] encodedKey = Base64.decodeBase64(salt);
        // 根据给定的字节数组使用AES加密算法构造一个密钥
        return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
    }

    public static Claims parseJWT(String jwt) {
        return parseJWT(jwt, Const.DEFAULT_SALT_TOKEN);
    }

    // 解密jwt

    public static Claims parseJWT(String jwt, String salt) {
        try {
            SecretKey key = generalKey(salt); // 签名秘钥，和生成的签名的秘钥一模一样
            return Jwts.parser() // 得到DefaultJwtParser
                    .setSigningKey(key) // 设置签名的秘钥
                    .parseClaimsJws(jwt)
                    .getBody();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exc("您的登录已失效请重新登录！");
        }
    }

    /**
     * 生成Token
     *
     * @param userid
     * @param salt
     * @param expireDuration
     * @return
     */
    public String generate(String userid, String salt, Long expireDuration) {
        try {

            long expireSecond;
            if (expireDuration == null) {
                expireSecond = 3600L;
            } else {
                expireSecond = expireDuration;
            }
            Map<String, Object> claims = new HashMap<>();
            claims.put("userid", userid);
            claims.put("ip", HttpContextUtil.getIp());
            Date expireDate = DateUtils.addSeconds(new Date(), (int) expireSecond);
            return Jwts
                    .builder()
                    .setClaims(claims)
                    .setId(IdUtils.original())
                    .setIssuedAt(new Date())
                    .setExpiration(expireDate)
                    .signWith(SignatureAlgorithm.HS512, generalKey(salt))
                    .compact();
        } catch (Exception e) {
            logger.error("生成Token失败" + e);
        }
        return null;
    }

    /**
     * 生成Token
     *
     * @param jwt
     * @param salt
     * @return
     */
    public static Boolean hasExpired(String jwt, String salt) {
        try {
            SecretKey key = generalKey(salt); // 签名秘钥，和生成的签名的秘钥一模一样
            Jwts.parser() // 得到DefaultJwtParser
                    .setSigningKey(key) // 设置签名的秘钥
                    .parseClaimsJws(jwt);
        } catch (ExpiredJwtException e) {
            return true;
        }
        return false;
    }
    /**
     * 无参获取Token
     */
    public static String getToken(){
        return getToken(HttpContextUtil.getHttpRequest());
    }
    /**
     * 获取Token
     * @param serverHttpRequest
     * @return
     */
    public static String getToken(ServerHttpRequest serverHttpRequest){
        HttpServletRequest request = null;
        if (serverHttpRequest == null){
            request = HttpContextUtil.getHttpRequest();
        }else{
            request = (HttpServletRequest) serverHttpRequest;
        }
        String token = request.getHeader("token");
        if (StringUtils.isBlank(token)){
            token = request.getParameter("token");
        }
        return token;
    }

    /**
     * 获取Token
     * @param HttpServletRequest
     * @return
     */
    public static String getToken(HttpServletRequest request) {
        if (request == null){
            request = HttpContextUtil.getHttpRequest();
        }
        String token = request.getHeader("token");
        if (StringUtils.isBlank(token)){
            token = request.getParameter("token");
        }
        return token;
    }

}
